#include "include.h"
#include "update_image_com.h"
#include "update_image_bim.h"
#include "sys_irq.h"
u_int32 udi_set_section_status_A_B(SECTION_BOUNDARY_PTR left, SECTION_BOUNDARY_PTR right)
{
    u_int32 status = SSTATUS_UNKOWN;
    if((FLASH_ERASED_CODE == left->signature)
            && (FLASH_ERASED_CODE == left->rsv[0])
            && (FLASH_ERASED_CODE == right->signature)
            && (FLASH_ERASED_CODE == right->rsv[0]))
    {
        status = SSTATUS_SECT_ERASED;
        goto exit_point;
    }
    if((UDI_SIGNATURE_CODE != left->signature) || (left->version != right->version))
    {
        status = SSTATUS_UPDATE_ABNORMAL;
        goto exit_point;
    }
    else
    {
        status = SSTATUS_UPDATE_NORMAL;
    }
    return status;
exit_point:
    return status;
}
void udi_get_psec_40_A_boundry(void)
{
    uint32 p_right_boundary_addr;
    fflash_rd_data((u_int8 *)&psec_A.left_boundary, (u_int32)PSEC_40_CRC_A_LEFT_BOUNDARY_ADDR, sizeof(psec_A.left_boundary));
    if(UDI_SIGNATURE_CODE == psec_A.left_boundary.signature)
    {
        p_right_boundary_addr = psec_A.left_boundary.sec_size + PSEC_40_A_LEFT_BOUNDARY_ADDR;
        fflash_rd_data((u_int8 *)&psec_A.right_boundary, crc_address(p_right_boundary_addr), sizeof(psec_A.right_boundary));
    }
    else
    {
        udi_memcpy(&psec_A.right_boundary, &psec_A.left_boundary, sizeof(psec_A.left_boundary));
    }
}
void udi_get_psec_40_B_boundry(void)
{
    uint32 p_right_boundary_addr;
    fflash_rd_data((u_int8 *)&psec_B.left_boundary, (u_int32)PSEC_40_CRC_B_LEFT_BOUNDARY_ADDR, sizeof(psec_B.left_boundary));
    if(UDI_SIGNATURE_CODE == psec_B.left_boundary.signature)
    {
        p_right_boundary_addr = psec_B.left_boundary.sec_size + PSEC_40_B_LEFT_BOUNDARY_ADDR;
        fflash_rd_data((u_int8 *)&psec_B.right_boundary, crc_address(p_right_boundary_addr), sizeof(psec_B.right_boundary));
    }
    else
    {
        udi_memcpy(&psec_B.right_boundary, &psec_B.left_boundary, sizeof(psec_B.left_boundary));
    }
}
u_int32 udi_erase_primary_section_A(void)
{
    u_int32 address;
    u_int32 total_len;
    udi_hex_int_print(PRT_ERASE_PSEC_A);
    total_len = PSEC_40_CRC_IMAGE_B_ADDR - PSEC_40_CRC_IMAGE_A_ADDR  ;
    address = PSEC_40_CRC_IMAGE_A_ADDR;
    fflash_unlock();
    fflash_wr_sr( 2,  0x0203 );
    udi_erase_section(address, total_len);
    fflash_unlock();
    fflash_wr_sr( 2,  0x0210 );
    fflash_lock();
    return 0;
}
u_int32 udi_erase_primary_section_B(void)
{
    u_int32 address;
    u_int32 total_len;
    udi_hex_int_print(PRT_ERASE_PSEC_B);
    total_len = crc_size((PRIMARY_40_SECTION_B_SIZE));
    address = PSEC_40_CRC_IMAGE_B_ADDR;
    fflash_unlock();
    fflash_wr_sr( 2,  0x022c );
    udi_erase_section(address, total_len);
    fflash_unlock();
    fflash_wr_sr( 2,  0x0210 );
    fflash_lock();
    return 0;
}
void udi_transfer_control_power_40_A_B(void)
{
    u_int32 main_point = PSEC_40_IMAGE_A_ADDR;
    udi_memset32((u_int8 *)0x00400000, 1, 1);
    udi_hex_int_print(PRT_TRANSFER_CONTROL_POWER);
    if(psec_A.sect_status == SSTATUS_UPDATE_NORMAL)
    {
        udi_memset32((u_int8 *)0x00400000, 1, 1);
        udi_hex_int_print(PRT_TRANSFER_CONTROL_POWER_A);
        udi_hex_int_print(PSEC_40_IMAGE_A_ADDR);
        main_point = PSEC_40_IMAGE_A_ADDR;
    }
    else if(psec_B.sect_status == SSTATUS_UPDATE_NORMAL)
    {
        udi_memset32((u_int8 *)0x00400000, 0, 1);
        udi_hex_int_print(PRT_TRANSFER_CONTROL_POWER_B);
        udi_hex_int_print(PSEC_40_IMAGE_B_ADDR);
        main_point = PSEC_40_IMAGE_B_ADDR;
    }
    else
    {
        udi_hex_int_print(PSEC_40_IMAGE_A_ADDR);
        udi_hex_int_print(PSEC_40_CRC_IMAGE_A_ADDR);
        udi_hex_int_print(PSEC_40_A_LEFT_BOUNDARY_ADDR);
        udi_hex_int_print(PSEC_40_CRC_A_LEFT_BOUNDARY_ADDR);
        udi_hex_int_print(PSEC_40_IMAGE_B_ADDR);
        udi_hex_int_print(PSEC_40_CRC_IMAGE_B_ADDR);
        udi_hex_int_print(PSEC_40_B_LEFT_BOUNDARY_ADDR);
        udi_hex_int_print(PSEC_40_CRC_B_LEFT_BOUNDARY_ADDR);
    }
    (*(FUNCPTR)main_point)();
}
uint32 udi_earse_image_AorB(void)
{
    uint32 need_earse_flag = 0;
    uint32 temp0 = 0;
    if(SSTATUS_UPDATE_ABNORMAL == psec_A.sect_status)
    {
        need_earse_flag = 1;
        udi_erase_primary_section_A();
    }
    if(SSTATUS_SECT_ERASED == psec_A.sect_status)
    {
        fflash_rd_data((uint8 *)&temp0,PSEC_40_CRC_IMAGE_A_ADDR,4);
        if(temp0 != FLASH_ERASED_CODE)
        {
            need_earse_flag = 2;
            udi_erase_primary_section_A();
        }
    }
    if(SSTATUS_UPDATE_ABNORMAL == psec_B.sect_status)
    {
        need_earse_flag = 3;
        udi_erase_primary_section_B();
    }
    if(SSTATUS_SECT_ERASED == psec_B.sect_status)
    {
        fflash_rd_data((uint8 *)&temp0,PSEC_40_CRC_IMAGE_B_ADDR,4);
        if(temp0 != FLASH_ERASED_CODE)
        {
            need_earse_flag = 4;
            udi_erase_primary_section_B();
        }
    }
    if((SSTATUS_UPDATE_NORMAL == psec_A.sect_status)
            && (SSTATUS_UPDATE_NORMAL == psec_B.sect_status) )
    {
        need_earse_flag = 5;
        udi_erase_primary_section_B();
    }
    return need_earse_flag;
}
int udi_image_status_print()
{
#if 1
    if(psec_A.sect_status == SSTATUS_SECT_ERASED)
    {
        udi_hex_int_print(PRT_PSECTION_A_STATUS_EARSED);
    }
    else if(psec_A.sect_status == SSTATUS_UPDATE_NORMAL)
    {
        udi_hex_int_print(PRT_PSECTION_A_STATUS_NORMAL);
    }
    else
    {
        udi_hex_int_print(PRT_PSECTION_A_STATUS_ABNORMAL);
    }
#endif
#if 1
    if(psec_B.sect_status == SSTATUS_SECT_ERASED)
    {
        udi_hex_int_print(PRT_PSECTION_B_STATUS_EARSED);
    }
    else if(psec_B.sect_status == SSTATUS_UPDATE_NORMAL)
    {
        udi_hex_int_print(PRT_PSECTION_B_STATUS_NORMAL);
    }
    else
    {
        udi_hex_int_print(PRT_PSECTION_B_STATUS_ABNORMAL);
    }
#endif
    return 0;
}
int udi_sect_image_40_A_B(void)
{
    //uint32 temp = 0;
    udi_get_psec_40_A_boundry();
    udi_get_psec_40_B_boundry();
    psec_A.sect_status = udi_set_section_status_A_B(&psec_A.left_boundary, &psec_A.right_boundary);
    psec_B.sect_status = udi_set_section_status_A_B(&psec_B.left_boundary, &psec_B.right_boundary);
    udi_image_status_print();
    udi_earse_image_AorB();

    return 0;
}
void udi_hw_init_bim(void)
{
    udi_wdt_disable();
    udi_icu_init();
    udi_uart_init();
    fflash_initialization();
}
int udi_main_bim(void)
{
    udi_hw_init_bim();
    udi_sect_image_40_A_B();
    udi_transfer_control_power_40_A_B();
    return 0;
}
